home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 029a / qbtree51.zip / XAPP1.BAS < prev   
BASIC Source File  |  1991-04-07  |  14KB  |  408 lines

  1. DECLARE SUB MoveIn (rec$, vseg%, voff%)
  2. DECLARE FUNCTION MoveOut$ (vseg%, voff%, bytes%)
  3. DECLARE FUNCTION Prepare$ (vseg%, voff%, bytes%)
  4. DECLARE FUNCTION OpenXAppFiles% ()
  5. DECLARE FUNCTION BuildXAppFiles% ()
  6. DECLARE FUNCTION ShowXAppFiles% ()
  7. DECLARE FUNCTION CreateXAppFiles% ()
  8.  
  9. DEFINT A-Z
  10. REM $INCLUDE: 'qbtree50.bi'
  11.  
  12. 'XAPP.BAS - an example application that exercises QBTREE.
  13. '(C)1991 Cornel Huth
  14. '07-Apr-1991
  15. '
  16. '------------------------------- DESCRIPTION --------------------------------
  17. '
  18. ' A) Primary key in EMP.DAT is EMP#. For each employee there is one and only
  19. ' one EMP# and for each EMP# there is one and only one employee. Each
  20. ' employee is assigned to a department. EMP.DAT:DEPT#, the foreign key,
  21. ' contains the department number he is assigned to.
  22. '
  23. ' Given an employee number (in EMP.DAT) you can find which department he is
  24. ' assigned. You can also find the name of his manager.
  25. '
  26. '
  27. ' B) Primary key in DEP.DAT is DEPT#. For each department there is one and
  28. ' only one DEPT# and for each DEPT# there is one and only one department.
  29. ' DEP.DAT:MGR#, the foreign key, contains the employee number of that
  30. ' department's manager.
  31. '
  32. ' Given a department number (in DEP.DAT) you can find the name of the
  33. ' manager of that department.
  34. '
  35. '
  36. ' C) Primary key in DEPEMP.DAT is DEP#+EMP#. Since each DEP# is unique and
  37. ' each EMP# is unique, combining the two you get a unique key. The DEP#
  38. ' portion of the key groups all EMP#'s in DEP# together allowing you to get
  39. ' all EMP#'s in a particular DEP#.
  40. '
  41. ' Given a department number (in DEPEMP.DAT) you can find all employees in
  42. ' that department. To get a unique primary key, the employee number is
  43. ' combined with the department number. With QBTREE you can specify a
  44. ' partial key (in this case just DEPT# with an EMP# of 0) and QBTREE will
  45. ' return the first DEPT#+EMP#. Using GetNext() you continue processing
  46. ' this until the DEPT# portion changes.
  47. '
  48. '
  49. '  ====  Primary key (field used to index this file)
  50. '                                              
  51. '  ----  Foreign key (field used to connect to another file's primary key)
  52. '                                             
  53. '  ≡≡≡≡  Used as both primary and foreign key
  54. '
  55. '                                               C) DEPEMP.DAT RECORD*
  56. '                                                 ┌───────┬──────┐
  57. '   ┌────────────────────────────── ─────┐         │ DEPT# │ EMP# │
  58. '   │                                    │         │ ===== │ ≡≡≡≡ │
  59. '     A) EMP.DAT RECORD                 │         └───────┴──────┘
  60. '┌──────┬───────────────┬────────┬────┐  └────────────────────┘
  61. '│ EMP# │ EMPLOYEE NAME │ DEPT#  │ WG │
  62. '│ ==== │               │ -----  │    │     B) DEP.DAT RECORD
  63. '└──────┴───────────────┴────────┴────┘   ┌───────┬───────────┬──────┐
  64. '                          │             │ DEPT# │ DEPT NAME │ MGR# │
  65. '   │                       └─────────── │ ====  │           │ ---- │
  66. '   │                                     └───────┴───────────┴──────┘
  67. '   │                                                            │
  68. '   └────────────────────────────────────────────────────────────┘
  69. '
  70. ' Example datafile contents:
  71. '
  72. '            EMP.DAT                  DEP.DAT        DEPEMP.DAT*
  73. '  EMP# EMPLOYEE NAME   D# WG    D# DEPT NAME  MGR#    D# EMP#
  74. '  ---- --------------- -- --    -- ---------- ----    -- ----
  75. '  1001 Frank Haas      12 15    10 Purchasing 1002    10 1002
  76. '  1002 Wendy Gibson    10 15    11 Accounting 2173    11 2173
  77. '  1125 Willie McAffee  14  9    12 Legal      1001    12 1001
  78. '  1507 David Robinson  13  9    13 MIS        1507    13 1507
  79. '  2173 Jackie Stewart  11 17    14 Personnel  1125    14 1125
  80. '  ... and so on                 ... and so on         ... and so on
  81. '
  82. ' * DEPEMP.DAT carries no information other than the DEP# in DEP.DAT
  83. ' and the EMP# in EMP.DAT. This means we do not need to carry a data
  84. ' file for the DEPEMP information. What is listed in this description
  85. ' as DEPEMP.DAT will actually be the index file itself (DEPEMP.NDX).
  86. '----------------------------------------------------------------------------
  87. '
  88. ' This program will output to the screen two logical tables. Table 1, the
  89. ' BY EMPLOYEE table, will have the employee's number, name, wage grade,
  90. ' department, and manager. Table 2, the BY DEPARTMENT table, will have a list of
  91. ' employees in each department.
  92. '
  93. '============================================================================
  94.  
  95. ' QBTREE file number equates
  96. CONST EMPdf = 0         'EMP.DAT QBTREE data file number
  97. CONST DEPdf = 1         'DEP.DAT
  98. CONST MDF = 1           'max data files needed (last data file number)
  99.  
  100. CONST EMPif = 0         'EMP.NDX QBTREE index file number
  101. CONST DEPif = 1         'DEP.NDX
  102. CONST DEPEMPif = 2      'DEPEMP.NDX
  103. CONST MKF = 2           'max key files needed (last key file number)
  104.  
  105. ' Employee data record type
  106. TYPE EmpDataTYPE
  107. Number AS STRING * 4
  108. Name AS STRING * 15
  109. DeptNo AS STRING * 2
  110. WG AS INTEGER
  111. END TYPE '23
  112. DIM SHARED EMP AS EmpDataTYPE
  113.  
  114. ' Department data record type
  115. TYPE DepDataTYPE
  116. Number AS STRING * 2
  117. Name AS STRING * 10
  118. MgrNo AS STRING * 4
  119. END TYPE '16
  120. DIM SHARED DEP AS DepDataTYPE
  121.  
  122. 'size FixedStr to largest TYPE structure used in QBTREE access
  123. DIM SHARED FixedStr AS STRING * 23
  124.  
  125. DIM SHARED XEmpData$
  126. DIM SHARED XDepData$
  127. DIM SHARED XEmpIndex$
  128. DIM SHARED XDepIndex$
  129. DIM SHARED XDepEmpIndex$
  130.  
  131. ' We'll create 3 key files and 2 data files using the info from the
  132. ' DATA statements below. Once built we'll show two tables based on the data
  133.  
  134. CLS
  135. stat = InitQBTREE(MKF, MDF)
  136. IF stat = 0 THEN
  137.    stat = CreateXAppFiles
  138.    IF stat = 0 THEN
  139.       stat = OpenXAppFiles
  140.       IF stat = 0 THEN
  141.          stat = BuildXAppFiles
  142.          IF stat = 0 THEN
  143.             stat = ShowXAppFiles
  144.             IF stat THEN
  145.                PRINT "Error"; stat; "from ShowXAppFiles"
  146.             END IF
  147.          ELSE
  148.             PRINT "Error"; stat; "from BuildXAppFiles"
  149.          END IF
  150.       ELSE
  151.          PRINT "Error"; stat; "from OpenXAppFiles"
  152.       END IF
  153.    ELSE
  154.       PRINT "Error"; stat; "from CreateXAppFiles"
  155.    END IF
  156. ELSE
  157.    PRINT "Error"; stat; "from InitQBTREE"
  158. END IF
  159. nul = ExitQBTREE
  160. END
  161.  
  162.  
  163. ' We'll use DATA statements to simplify getting the initial data
  164.  
  165. ' XApp employee data
  166. EmpData:
  167. DATA 11
  168. DATA 1001,Frank Hass,12,15
  169. DATA 1002,Wendy Gibson,10,15
  170. DATA 1125,Willie McAffee,14,9
  171. DATA 1507,David Robinson,13,9
  172. DATA 1173,Jackie Stewart,11,17
  173. DATA 4105,Beatrice South,10,5
  174. DATA 4288,Jim Davies,10,5
  175. DATA 4901,Tom Cassidy,14,4
  176. DATA 3149,Nancy Cannon,13,7
  177. DATA 3510,John Madison,12,12
  178. DATA 3685,Chris Ho,13,9
  179.  
  180. ' XApp department data
  181. DepData:
  182. DATA 5
  183. DATA 10,Purchasing,1002
  184. DATA 11,Accounting,1173
  185. DATA 12,Legal,1001
  186. DATA 13,MIS,1507
  187. DATA 14,Personnel,1125
  188.  
  189. FUNCTION BuildXAppFiles
  190.  
  191. 'using the info in the DATA statements build the XApp files
  192.  
  193. PRINT "Building employee data and index files...";
  194. RESTORE EmpData
  195. READ EmpRecs
  196. FOR i = 1 TO EmpRecs
  197.    READ EMP.Number, EMP.Name, EMP.DeptNo, EMP.WG
  198.    key$ = EMP.Number
  199.    rec$ = MoveOut$(VARSEG(EMP), VARPTR(EMP), LEN(EMP))
  200.    stat = AddKeyRecord(EMPif, EMPdf, key$, rec$)
  201.    IF stat THEN EXIT FOR
  202. NEXT
  203. IF stat = 0 THEN
  204.    PRINT "ok."
  205.    PRINT "Building department data and index files...";
  206.    RESTORE DepData
  207.    READ DepRecs
  208.    FOR i = 1 TO DepRecs
  209.       READ DEP.Number, DEP.Name, DEP.MgrNo
  210.       key$ = DEP.Number
  211.       rec$ = MoveOut$(VARSEG(DEP), VARPTR(DEP), LEN(DEP))
  212.       stat = AddKeyRecord(DEPif, DEPdf, key$, rec$)
  213.       IF stat THEN EXIT FOR
  214.    NEXT
  215.    IF stat = 0 THEN
  216.       PRINT "ok."
  217.       PRINT "Building department+employee index file...";
  218.  
  219.       ' to build this index file we use the employee file just built.
  220.       ' a shortcoming of this is that departments with no employees
  221.       ' (unlikely) assigned will not be represented in the index file.
  222.  
  223.       recno& = 0 'we won't be needing data record pointers for StoreKey()
  224.  
  225.       stat = GetFirst(EMPif, EMPdf, key$, rec$)
  226.       DO WHILE stat = 0
  227.  
  228.          'rec$ contains employee data record info, move it to EMP structure
  229.          MoveIn rec$, VARSEG(EMP), VARPTR(EMP)
  230.  
  231.          'EMP.DeptNo and EMP.Number are string so we can forego MoveOut$()
  232.          key$ = EMP.DeptNo + EMP.Number
  233.          
  234.          stat = StoreKey(DEPEMPif, key$, recno&)
  235.          IF stat = 0 THEN stat = GetNext(EMPif, EMPdf, key$, rec$)
  236.       LOOP
  237.       IF stat = 202 THEN stat = 0  'End of file is expected
  238.       IF stat = 0 THEN PRINT "ok."
  239.  
  240.    END IF
  241. END IF
  242. BuildXApp = stat
  243.  
  244. END FUNCTION
  245.  
  246. FUNCTION CreateXAppFiles
  247.  
  248. ' Create the XApp files. If they already exist delete them first.
  249.  
  250. PRINT "Creating XApp Files...";
  251.  
  252. XEmpData$ = "EMP.DAT"
  253. XDepData$ = "DEP.DAT"
  254. XEmpIndex$ = "EMP.NDX"
  255. XDepIndex$ = "DEP.NDX"
  256. XDepEmpIndex$ = "DEPEMP.NDX"
  257.  
  258. IF FileExists(XEmpData$) THEN KILL XEmpData$
  259. IF FileExists(XDepData$) THEN KILL XDepData$
  260. IF FileExists(XEmpIndex$) THEN KILL XEmpIndex$
  261. IF FileExists(XDepIndex$) THEN KILL XDepIndex$
  262. IF FileExists(XDepEmpIndex$) THEN KILL XDepEmpIndex$
  263.  
  264. stat = CreateDataFile(XEmpData$, LEN(EMP))
  265. IF stat = 0 THEN stat = CreateDataFile(XDepData$, LEN(DEP))
  266. IF stat = 0 THEN stat = CreateKeyFile(XEmpIndex$, LEN(EMP.Number))
  267. IF stat = 0 THEN stat = CreateKeyFile(XDepIndex$, LEN(DEP.Number))
  268. IF stat = 0 THEN stat = CreateKeyFile(XDepEmpIndex$, LEN(EMP.Number) + LEN(DEP.Number))
  269.  
  270. IF stat = 0 THEN PRINT "ok."
  271. CreateXAppFiles = stat
  272.  
  273. END FUNCTION
  274.  
  275. SUB MoveIn (rec$, vseg, voff)
  276.  
  277. ' copy the variable-length string data from rec$ (which may contain
  278. ' non-string data) to the TYPEd structure pointed to by vseg:voff.
  279. ' See MoveOut$() for more.
  280.  
  281. FixedStr = rec$
  282. MEMCOPY VARSEG(FixedStr), VARPTR(FixedStr), vseg, voff, LEN(rec$)
  283.  
  284. END SUB
  285.  
  286. FUNCTION MoveOut$ (vseg, voff, bytes)
  287.  
  288. ' copy the data from the TYPEd structure pointed to by vseg:voff
  289. ' to a fixed-length string. We use a fixed-length string so that
  290. ' we don't need to concern ourselves with being both QB4 and PDS /Fs
  291. ' compatible. Simple fixed-length strings are in DGROUP for both
  292. ' QB and QBX. Note: FixedStr needs to be sized to at least the largest
  293. ' TYPE structure size (23 bytes for XEmpData).
  294.  
  295. 'IF bytes > LEN(FixedStr) THEN STOP  'useful in debugging stage
  296.  
  297. MEMCOPY vseg, voff, VARSEG(FixedStr), VARPTR(FixedStr), bytes
  298. MoveOut$ = LEFT$(FixedStr, bytes)
  299.  
  300. END FUNCTION
  301.  
  302. FUNCTION OpenXAppFiles
  303.  
  304. PRINT "Opening XApp Files...";
  305.  
  306. stat = OpenDataFile(XEmpData$, EMPdf)
  307. IF stat = 0 THEN stat = OpenDataFile(XDepData$, DEPdf)
  308. IF stat = 0 THEN stat = OpenKeyFile(XEmpIndex$, EMPif)
  309. IF stat = 0 THEN stat = OpenKeyFile(XDepIndex$, DEPif)
  310. IF stat = 0 THEN stat = OpenKeyFile(XDepEmpIndex$, DEPEMPif)
  311.  
  312. IF stat = 0 THEN PRINT "ok."
  313. OpenXAppFiles = stat
  314.  
  315. END FUNCTION
  316.  
  317. FUNCTION ShowXAppFiles
  318.  
  319. CLS
  320. PRINT "****************** BY EMPLOYEE ********************"
  321. PRINT
  322. PRINT "EMP#     EMPLOYEE      GRADE  DEPARTMENT       MANAGER"
  323. PRINT "----  ---------------   ---   ----------   ---------------"
  324.  
  325. ' get the first employee's info
  326. stat = GetFirst(EMPif, EMPdf, key$, rec$)
  327. DO WHILE stat = 0
  328.  
  329.    ' move the employee record data to the EMP structure
  330.    MoveIn rec$, VARSEG(EMP), VARPTR(EMP)
  331.    LastKey$ = EMP.Number
  332.    PRINT EMP.Number;
  333.    LOCATE , 7: PRINT EMP.Name;
  334.    t$ = SPACE$(3)
  335.    RSET t$ = STR$(EMP.WG)       'right-align wage grade
  336.    LOCATE , 24: PRINT t$;
  337.  
  338.    ' go get the department info for this employee
  339.    stat = GetEqual(DEPif, DEPdf, EMP.DeptNo, rec$)
  340.    IF stat = 0 THEN
  341.  
  342.       ' move department record data to the DEP structure
  343.       MoveIn rec$, VARSEG(DEP), VARPTR(DEP)
  344.       LOCATE , 31: PRINT DEP.Name;
  345.  
  346.       ' go get the manager's name
  347.       stat = GetEqual(EMPif, EMPdf, DEP.MgrNo, rec$)
  348.       IF stat = 0 THEN
  349.          
  350.           ' move manager's record data to EMP structure (he is an employee)
  351.           MoveIn rec$, VARSEG(EMP), VARPTR(EMP)
  352.           LOCATE , 44: PRINT EMP.Name
  353.       END IF
  354.  
  355.       ' we need to reposition to the last employee (getting the manager's
  356.       ' name messed things up a bit) and then get the next employee
  357.       stat = GetEqual(EMPif, EMPdf, LastKey$, rec$)
  358.       IF stat = 0 THEN stat = GetNext(EMPif, EMPdf, key$, rec$)
  359.  
  360.    END IF
  361. LOOP
  362. IF stat = 202 THEN stat = 0
  363.  
  364. IF stat = 0 THEN
  365.    PRINT
  366.    PRINT "******************************** BY DEPARTMENT *******************************"
  367.    PRINT
  368.    PRINT "  Purchasing      Accounting         Legal           MIS          Personnel"
  369.    PRINT "--------------- --------------- --------------- -------------- ---------------"
  370.    p10 = CSRLIN: p11 = p10: p12 = p10: p13 = p10: p14 = p10
  371.  
  372.    stat = RetrieveFirst(DEPEMPif, key$, recno&)
  373.    DO WHILE stat = 0
  374.  
  375.       ' we know that the EMP# is bytes 3-6 of the key so
  376.       ' get the name of this EMP# (DEP# is bytes 1-2)
  377.       Dept$ = LEFT$(key$, 2)
  378.       Ekey$ = MID$(key$, 3, 4)
  379.       stat = GetEqual(EMPif, EMPdf, Ekey$, Erec$)
  380.       MoveIn Erec$, VARSEG(EMP), VARPTR(EMP)
  381.       
  382.       SELECT CASE Dept$
  383.       CASE "10"
  384.          LOCATE p10, 1
  385.          p10 = p10 + 1
  386.       CASE "11"
  387.          LOCATE p11, 17
  388.          p11 = p11 + 1
  389.       CASE "12"
  390.          LOCATE p12, 33
  391.          p12 = p12 + 1
  392.       CASE "13"
  393.          LOCATE p13, 49
  394.          p13 = p13 + 1
  395.       CASE "14"
  396.          LOCATE p14, 64
  397.          p14 = p14 + 1
  398.       CASE ELSE
  399.       END SELECT
  400.       PRINT EMP.Name
  401.  
  402.       stat = RetrieveNext(DEPEMPif, key$, recno&)
  403.    LOOP
  404. END IF
  405.  
  406. END FUNCTION
  407.  
  408.